#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : lei.wang
import os
import requests
from requests import RequestException
from rest_framework import serializers
from rest_framework.exceptions import APIException
from typing import Union
from pydantic import BaseModel, SecretStr, field_validator
from apps.utils.exceptions import NotFoundOpenIdException
from apps.user.models import User


class WeixinServicesConfig(BaseModel):

    wx_appid: str
    wx_secret: SecretStr
    wx_openid_url: str

    @field_validator('wx_appid')
    def validate_wx_appid(cls, wx_appid: str):
        if not wx_appid:
            raise serializers.ValidationError('wx_appid 不能为空')
        return wx_appid

    @field_validator('wx_secret')
    def validate_wx_secret(cls, wx_secret: str):
        if not wx_secret:
            raise serializers.ValidationError('wx_secret 不能为空')
        return wx_secret

    @field_validator('wx_openid_url')
    def validate_wx_openid_url(cls, wx_openid_url: str):
        if not wx_openid_url:
            raise serializers.ValidationError('wx_openid_url 不能为空')
        return wx_openid_url


class WeixinServices(object):

    @staticmethod
    def get_openid_session_with_code(code: str) -> Union[
        serializers.ValidationError, tuple, APIException, RequestException
    ]:
        wx_config = WeixinServicesConfig(**{
            'wx_appid': os.environ.get('WX_APPID', ''),
            'wx_secret': os.environ.get('WX_SECRET', ''),
            'wx_openid_url': os.environ.get('WX_OPENID_URL', ''),
        })
        response = requests.get(
            wx_config.wx_openid_url.format(wx_config.wx_appid, wx_config.wx_secret.get_secret_value(), code),
            timeout=5,
        )
        response.raise_for_status()
        data = response.json()
        if 'openid' not in data:
            raise NotFoundOpenIdException()

        openid = data.get('openid')
        session_key = data.get('session_key')
        return openid, session_key

    @staticmethod
    def save_openid_session(openid: str, session_key: str) -> User:
        user = User.objects.filter(wei_chat_open_id=openid).first()
        if not user:
            return User.objects.create(wei_chat_open_id=openid, session_key=session_key)
        return user
